﻿using System;
using System.Text;
using Abp.Auditing;
using Microsoft.EntityFrameworkCore;

namespace AbpDevelopmentLog.EntityFrameworkCore.Seed.Host
{
    public class TablePartitionBuilder
    {
        private readonly AbpDevelopmentLogDbContext _context;

        public static string PartitionByDay;

        public TablePartitionBuilder(AbpDevelopmentLogDbContext context)
        {
            _context = context;
        }


        public void Create()
        {
            PartitionByDay = GetDayPartitionByDaySql();
            AlterAuditLog();
        }

        private void AlterAuditLog()
        {
            var tableName = GetTableName<AuditLog>();
            var sql = string.Format(PartitionByDay, tableName, "ExecutionTime");
            Console.WriteLine(sql);
            _context.Database.ExecuteSqlCommand(sql);
        }


        private static string GetDayPartitionByDaySql()
        {
            var stringBuilder = new StringBuilder();
            stringBuilder.AppendLine("ALTER TABLE `{0}`");
            stringBuilder.AppendLine("PARTITION BY RANGE(to_days(`{1}`))( ");
            var currentYear = DateTime.Now.Year;
            for (var i = 0; i < 2; i++)
            {
                var year = currentYear + i;
                for (var j = 1; j <= 12; j++)
                {
                    var days = DateTime.DaysInMonth(year, j);
                    for (var k = 1; k <= days; k++)
                    {
                        stringBuilder.AppendLine(
                            $"PARTITION p{year}{j:00}{k:00} VALUES LESS THAN (to_days('{year}-{j:00}-{k:00}')),");
                    }
                }
            }
            stringBuilder.AppendLine("PARTITION pmax VALUES LESS THAN (MAXVALUE)");
            stringBuilder.AppendLine(");");
            return stringBuilder.ToString();
        }

        private string GetTableName<T>()
        {
            var mapping = _context.Model.FindEntityType(typeof(T)).Relational();
            return mapping.TableName;
        }

    }
}